#ifndef AGGREGATEDFUNCTIONBOX_H_JM_20130222
#define AGGREGATEDFUNCTIONBOX_H_JM_20130222

// ## 
#include "../BufferedOutputBox.h"
#include "../../LogConf.h"

namespace jm4bbx {

	class  AggregatedFunctionBox 
		: public BufferedOneOutputBox<integerType> {
		JM_USE_LOGGER(boxes_aggregateFunctions_AggregatedFunctionBox_logger)
	public:
		static const  groupType INPUT_GROUP;
		static const  groupType OUTPUT_GROUP;	
		static const  columnType INPUT_COLUMN;
		static const  columnType OUTPUT_COLUMN;
		static const  inType IN_ARC;
		static const  outType OUT_ARC;

		AggregatedFunctionBox(const BoxParamPack& p) 
			: BufferedOneOutputBox(p, OUTPUT_GROUP, OUTPUT_COLUMN, OUT_ARC) { }


		virtual void initAggregatedValue() = 0;
		virtual void aggregateValue(int vlaue) = 0;
		virtual void outputAggregatedValue() = 0;

		virtual void initImpl() {
			add_group(INPUT_GROUP, INPUT_COLUMN, 
				get_input_descriptors(IN_ARC));

			add_group(OUTPUT_GROUP, OUTPUT_COLUMN, 
				get_output_descriptors(OUT_ARC));

			initBufferedOutputs();

			wait4Receive();
		}


		virtual void syncMachEtwas() {

			GroupPtr ig = getGroupPtr(INPUT_GROUP);

			initAggregatedValue();

			for (; ig->getReadPosition() < ig->getReadEnd(); ig->moveReadPosition()) {								
				auto value = get_data<IntegerKeyRecord>(
					INPUT_COLUMN)[ig->getReadPosition()].getKey();
				LOG_D("aggregate value: " << value)
				aggregateValue(value);				

			}
			outputAggregatedValue();
			// Priechod datami ktore sa maju spracovat. 
			sendOutputData();


			assert(!(ig->getReadPosition() < ig->getReadEnd()));
			assert(isOutputEmpty());

			send_poisoned(OUT_ARC);
			sendSignalsOut(true);
			wait4Receive();
		}

		
	private:
		/// Zahajenie cakania na vstup.
		void wait4Receive() {
			receive(IN_ARC, INPUT_GROUP);
		}
	};

} // namespace jm4bbx	

#endif
